home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr47
/
wasm223.zip
/
TABS.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-05-05
|
16KB
|
490 lines
;================================================
; TABS By Eric Tauck
;
; This program optimally compresses all spaces to
; tab characters or expands all tab characters to
; spaces. Additionally, spaces and tabs are
; removed from the end of lines and blank lines
; are removed from the end of files. These func-
; tions are useful for cleaning up and compres-
; sing source files (especially assembler files).
;
; The usage is:
;
; TABS source [target] [/C] [/X]
;
; If 'target' is not present, a temporary file
; ('source.$$$') becomes the target and is later
; renamed to 'source' after deleting 'source'.
; /C specifies compression to tabs (this is the
; default). /X specifies expansion to spaces.
; Note that tabs are fixed at every 8 spaces.
;
; This program uses the WASM library files.
JUMP+ ;let's optimize jumps
;--- library files
INCLUDE 'library\start'
INCLUDE 'library\buffer1'
INCLUDE 'library\buffer2'
INCLUDE 'library\buffer3'
INCLUDE 'library\case1'
INCLUDE 'library\case2'
INCLUDE 'library\string'
INCLUDE 'library\file'
INCLUDE 'library\memory'
INCLUDE 'library\message1'
INCLUDE 'library\parms'
;--- a few equates
BUFSIZE EQU 50000 ;read and write buffer sizes
TAB EQU 9 ;tab
LF EQU 10 ;linefeed
CR EQU 13 ;carriage return
EOF EQU 26 ;end of file marker
;--- program entry point
mov ax, OFFSET banner ;banner address
call MesPutL ;display
;=== set up parameters
mov di, 1 ;initial parameter number
main1 call ParGet ;get parameter
jc main6 ;jump if no more
mov si, ax ;save in SI
call StrUpr ;convert to uppercase
;--- check if expand option
mov ax, si
mov bx, OFFSET opt_exp ;option string
call StrCmp ;check if option
jc main2 ;jump if not
or flags, NO_COMP ;set flag
jmps main1
;--- check if compress option
main2 mov ax, si
mov bx, OFFSET opt_com ;option string
call StrCmp ;check if option
jc main3 ;jump if not
and flags, NOT NO_COMP ;clear flag
jmps main1
;--- check if source name
main3 cmp di, 1 ;check if source
jne main4 ;jump if not
mov srcname, si ;save source name
inc di
jmps main1
;--- check if destination name
main4 cmp di, 2 ;check if destination
jnz main5 ;jump if not
mov desname, si ;save destination name
inc di
jmps main1
;--- incorrect parameters
main5 mov ax, OFFSET help ;help message
sub bp, bp ;no file name
jmp error2 ;branch to error
;--- check file names, maybe create temporary file
;
; NOTE: this will not work correctly if the source file contains a
; short filespec with a directory containing an extension, for
; example: X.Y\A -- will think .Y\A is extension.
main6 cmp srcname, 0FFFFH ;check if no source
je main5
cmp desname, 0FFFFH ;check if no destination
jne main9
or flags, DO_REN ;set rename flag
mov ax, srcname ;source name
mov bx, OFFSET desfnam ;storage for destination name
mov desname, bx ;save address
push bx ;save for later
call StrCpy ;copy source name
pop ax
mov di, ax
call Strlen ;get length
add di, ax ;add point to end byte
mov si, di ;save for adding ext if no dot
dec di ;adjust to last byte
cmp ax, 4 ;check if 4 or less
jbe main7 ;jump if so
mov ax, 4 ;max 4 bytes to search
main7 mov cx, ax ;bytes to scan
mov al, '.' ;look for dot
std
repne ;for length
scasb ;scan for dot
jne main8 ;jump if not found
mov si, di ;source
inc si ;point to dot
main8 mov ax, OFFSET exten ;extension
mov bx, si ;place to put it
call StrCpy ;copy it
;--- set up file records
main9 mov si, OFFSET srcfile ;source file record
mov di, OFFSET desfile ;destination file record
mov ax, BUFSIZE ;bytes for buffer
mov bx, si ;file record
call BufAll ;allocate buffer
jc mainC ;jump if error
mov ax, BUFSIZE ;bytes for buffer
mov bx, di ;file record
call BufAll ;allocate buffer
jnc mainA ;jump if okay
mov bx, si
call BufRel ;release first buffer before error
jmps mainC
;=== process files
mainA call Open ;open files
jc mainD
call Process ;process files
jc mainE
call Close ;close files
jc mainE
;--- finished
mov bx, di
call BufRel ;release buffer
mov bx, si
call BufRel ;release buffer
;--- delete and rename
test flags, DO_REN ;check if rename
jz mainB
mov ah, 41H ;delete function
mov dx, srcname ;name of file
int 21H ;execute
mov ah, 56H ;rename function
mov dx, desname ;current name
mov di, srcname ;target name
int 21H ;execute
;--- terminate
mainB mov ax, 4C00H ;terminate function
int 21H ;execute
;--- memory allocation error
mainC mov ax, OFFSET emess1
sub bp, bp
jmps error2
;--- file open or creation error
mainD mov ax, OFFSET emess2
jmps error1
;--- file read or write error
mainE mov ax, OFFSET emess3
;--- error message in AX, file name in BP
error1 push ax
mov bx, di
call BufRel ;release buffer
mov bx, si
call BufRel ;release buffer
pop ax
error2 or bp, bp ;check if file name
jz error3 ;jump if not
call MesPut ;display message
mov ax, bp
error3 call MesPutL ;display file name / error message
mov ax, 4CFFH ;exit with error code 256
int 21H ;execute
;========================================
; Open files.
;
; In: SI and DI= source and destination
; buffer records.
;
; Out: CY= set if error; BP= name of file
; if error.
Open PROC NEAR
mov ax, srcname ;source file
mov bp, ax
mov bx, si ;buffer record
mov cl, BUFFER_READ ;read
call BufOpn ;open buffer
jc Open1 ;jump if error
mov ax, desname ;destination file
mov bp, ax
mov bx, di ;buffer record
mov cl, BUFFER_CREATE ;create
call BufOpn ;open buffer
Open1 ret
ENDP
;========================================
; Close files.
;
; In: SI and DI= source and destination
; buffer records.
;
; Out: CY= set if error; BP= name of file
; if error.
Close PROC NEAR
mov bp, desname ;name of file if error
mov bx, di
call BufPut ;flush destination buffer
jc Close1
mov bx, di
call BufClo ;close destination buffer
mov bx, si
call BufClo ;close source buffer
clc
Close1 ret
ENDP
;========================================
; Process files.
;
; In: SI and DI= buffer record addresses.
;
; Out: CY= set if error; BP= name of file
; if error.
Process PROC NEAR
sub bp, bp ;zero column
jmps Proces7
;--- end of file or error reading
Proces1 or al, al ;check if really error
jnz Proces4 ;jump if so
Proces2 cmp lincnt, 0 ;check if any saved lines
je Proces3
mov lincnt, 1 ;write one line
mov tabcnt, 0 ;zero tab count
mov spccnt, 0 ;zero space count
Proces3 call Write ;write
jc Proces5
mov al, EOF ;end of file
mov bx, di ;buffer record
call PutByt ;write byte
jc Proces5
clc
ret
;--- error reading
Proces4 mov bp, srcname
stc
ret
;--- error writing
Proces5 mov bp, desname
stc
ret
;--- found space
Proces6 Check ;check if tab
inc spccnt ;increment spaces
inc bp ;increment column
;=== main processing loop
Proces7 mov bx, si
call GetByt ;read a byte
jc Proces1
cmp al, ' ' ;check if space
je Proces6
cmp al, TAB ;check if tab
je Proces9
cmp al, CR ;check if carriage return
je Proces7
cmp al, LF ;check if linefeed
je ProcesB
cmp al, EOF ;check if end of file
je Proces2
;--- found text character
Check ;check if tab
inc bp ;increment column
mov dx, spccnt ;space count
or dx, tabcnt ;or tab count
or dx, lincnt ;or line count
jnz ProcesC ;jump if any set
Proces8 mov bx, di
call PutByt ;write character
jnc Proces7 ;loop back if no error
jmps Proces5
;--- found tab
Proces9 mov cx, bp ;load column
and cx, 111B ;mask odd space bits
sub cx, 8 ;spaces in tab
neg cx ;adjust
ProcesA Check ;check if tab
inc spccnt ;increment spaces
inc bp ;increment column
loop ProcesA ;loop for each space
jmp Proces7
;--- found linefeed
ProcesB inc lincnt ;increment line count
mov tabcnt, 0 ;zero tab count
mov spccnt, 0 ;zero space count
sub bp, bp ;zero column number
jmp Proces7
;--- stored characters before a text character
ProcesC push ax
call Write ;write stored stuff
pop ax
jnc Proces8 ;jump back if okay
jmp Proces5
ENDP
;========================================
; Check if should output tab.
Check MACRO
test flags, NO_COMP ;check if no compress
jnz Check1 ;jump if so
cmp spccnt, 0 ;check if any stored spaces
jz Check1 ;jump if not
test bp, 111B ;check if at tab stop
jnz Check1 ;jump if not
inc tabcnt ;increment tabs
mov spccnt, 0 ;reset space count
Check1
ENDM
;========================================
; Write saved stuff.
Write PROC NEAR
;--- store saved lines
cmp lincnt, 0 ;check if any lines
je Write2 ;skip if not
Write1 mov al, CR ;carriage return
mov bx, di ;buffer record
call PutByt ;write byte
jc Write7 ;jump if error
mov al, LF ;linefeed
mov bx, di ;buffer record
call PutByt ;write byte
jc Write7 ;jump if error
dec lincnt ;decrement line count
jnz Write1 ;loop back if more
;--- store saved tabs
Write2 cmp tabcnt, 0 ;check if any tabs
je Write4 ;skip if not
Write3 mov al, TAB ;tab character
mov bx, di ;buffer record
call PutByt ;write byte
jc Write7 ;jump if error
dec tabcnt ;decrement count
jnz Write3 ;loop back if more
;--- store saved spaces
Write4 cmp spccnt, 0 ;check if any spaces
je Write6 ;skip if not
Write5 mov al, ' ' ;space character
mov bx, di ;buffer record
call PutByt ;write byte
jc Write7 ;jump if error
dec spccnt ;decrement count
jnz Write5 ;loop back if more
Write6 clc
Write7 ret
ENDP
;========================================
; Data.
spccnt DW 0 ;space count
tabcnt DW 0 ;tab count
lincnt DW 0 ;line end count
;--- flags
NO_COMP EQU 1B ;don't compress spaces
DO_REN EQU 10B ;rename output file and delete input file
flags DB 0
;--- text
opt_com DB '/C',0
opt_exp DB '/X',0
exten DB '.$$$',0
banner DB 13,10,'TABS Version 1.00 Eric Tauck 2/20/90',0
emess1 DB 13,10,'Not enough memory for buffers',0
emess2 DB 13,10,'Could not open or create file: ',0
emess3 DB 13,10,'Error reading or writing file: ',0
help DB 13,10
DB 'Usage: TABS source [target] [/C] [/X]',13,10
DB 13,10
DB ' /C compresses spaces to tabs',13,10
DB ' /X expands tabs to spaces'
DB 0
;--- file names
srcname DW 0FFFFH ;address of source file
desname DW 0FFFFH ;address of destination file name
;--- uninitialized file data
srcfile LABEL BYTE ;source file record
ORG +BUFFER_RECORD
desfile LABEL BYTE ;destination file record
ORG +BUFFER_RECORD
desfnam LABEL WORD ;destination name if none specified
ORG +129